﻿#include "StdAfx.h"
#include "UIWebBrowser.h"
#include <atlconv.h>
#include <atlcomcli.h>
#include "../Utils/downloadmgr.h"
#include <mshtml.h>

namespace DuiLib
{
    ////////////////////////////////////////////////////////////////////////
    //
    IMPLEMENT_DUICONTROL(CWebBrowserUI)

        CWebBrowserUI::CWebBrowserUI()
        : m_pWebBrowser2(NULL)
        , _pHtmlWnd2(NULL)
        , m_pWebBrowserEventHandler(NULL)
        , m_bAutoNavi(false)
        , m_dwRef(0)
        , m_dwCookie(0)
    {
        m_clsid=CLSID_WebBrowser;
        m_sHomePage.Empty();
    }

    bool CWebBrowserUI::DoCreateControl()
    {
        if (!CActiveXUI::DoCreateControl())
            return false;
        GetManager()->AddTranslateAccelerator(this);
        GetControl(IID_IWebBrowser2,(LPVOID*)&m_pWebBrowser2);
        if ( m_bAutoNavi && !m_sHomePage.IsEmpty())
        {
            this->Navigate2(m_sHomePage);
        }
        RegisterEventHandler(TRUE);
        return true;
    }

    void CWebBrowserUI::ReleaseControl()
    {
        m_bCreated=false;
        GetManager()->RemoveTranslateAccelerator(this);
        RegisterEventHandler(FALSE);
    }

    CWebBrowserUI::~CWebBrowserUI()
    {
        ReleaseControl();
    }

    STDMETHODIMP CWebBrowserUI::GetTypeInfoCount( UINT *iTInfo )
    {
        *iTInfo = 0;
        return E_NOTIMPL;
    }

    STDMETHODIMP CWebBrowserUI::GetTypeInfo( UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo )
    {
        return E_NOTIMPL;
    }

    STDMETHODIMP CWebBrowserUI::GetIDsOfNames( REFIID riid, OLECHAR **rgszNames, UINT cNames, LCID lcid,DISPID *rgDispId )
    {
        return E_NOTIMPL;
    }

    STDMETHODIMP CWebBrowserUI::Invoke( DISPID dispIdMember, REFIID riid, LCID lcid,WORD wFlags, DISPPARAMS* pDispParams,VARIANT* pVarResult, EXCEPINFO* pExcepInfo,UINT* puArgErr )
    {
        if ((riid != IID_NULL))
            return E_INVALIDARG;

        switch(dispIdMember)
        {
        case DISPID_BEFORENAVIGATE2:
            BeforeNavigate2(
                pDispParams->rgvarg[6].pdispVal,
                pDispParams->rgvarg[5].pvarVal,
                pDispParams->rgvarg[4].pvarVal,
                pDispParams->rgvarg[3].pvarVal,
                pDispParams->rgvarg[2].pvarVal,
                pDispParams->rgvarg[1].pvarVal,
                pDispParams->rgvarg[0].pboolVal);
            break;
        case DISPID_COMMANDSTATECHANGE:
            CommandStateChange(
                pDispParams->rgvarg[1].lVal,
                pDispParams->rgvarg[0].boolVal);
            break;
        case DISPID_NAVIGATECOMPLETE2:
            NavigateComplete2(
                pDispParams->rgvarg[1].pdispVal,
                pDispParams->rgvarg[0].pvarVal);
            break;
        case DISPID_NAVIGATEERROR:
            NavigateError(
                pDispParams->rgvarg[4].pdispVal,
                pDispParams->rgvarg[3].pvarVal,
                pDispParams->rgvarg[2].pvarVal,
                pDispParams->rgvarg[1].pvarVal,
                pDispParams->rgvarg[0].pboolVal);
            break;
        case DISPID_STATUSTEXTCHANGE:
            break;
            //      case DISPID_NEWWINDOW2:
            //          break;
        case DISPID_NEWWINDOW3:
            NewWindow3(
                pDispParams->rgvarg[4].ppdispVal,
                pDispParams->rgvarg[3].pboolVal,
                pDispParams->rgvarg[2].uintVal,
                pDispParams->rgvarg[1].bstrVal,
                pDispParams->rgvarg[0].bstrVal);
            break;
        case DISPID_TITLECHANGE:
            {
                TitleChange(pDispParams->rgvarg[0].bstrVal);
                break;
            }
        case DISPID_DOCUMENTCOMPLETE:
            {
                DocumentComplete(
                    pDispParams->rgvarg[1].pdispVal,
                    pDispParams->rgvarg[0].pvarVal);

                break;
            }
        default:
            return DISP_E_MEMBERNOTFOUND;
        }
        return S_OK;
    }

    STDMETHODIMP CWebBrowserUI::QueryInterface( REFIID riid, LPVOID *ppvObject )
    {
        *ppvObject = NULL;

        if( riid == IID_IDocHostUIHandler)
            *ppvObject = static_cast<IDocHostUIHandler*>(this);
        else if( riid == IID_IDispatch)
            *ppvObject = static_cast<IDispatch*>(this);
        else if( riid == IID_IServiceProvider)
            *ppvObject = static_cast<IServiceProvider*>(this);
        else if(riid == IID_IInternetSecurityManager ) {
            *ppvObject = static_cast<IInternetSecurityManager*>(this);
        }
        else if (riid == IID_IOleCommandTarget)
            *ppvObject = static_cast<IOleCommandTarget*>(this);

        if( *ppvObject != NULL )
            AddRef();
        return *ppvObject == NULL ? E_NOINTERFACE : S_OK;
    }

    STDMETHODIMP_(ULONG) CWebBrowserUI::AddRef()
    {
        InterlockedIncrement(&m_dwRef); 
        return m_dwRef;
    }

    STDMETHODIMP_(ULONG) CWebBrowserUI::Release()
    {
        ULONG ulRefCount = InterlockedDecrement(&m_dwRef);
        return ulRefCount; 
    }

    void CWebBrowserUI::Navigate2( LPCTSTR lpszUrl )
    {
        if (lpszUrl == NULL)
            return;

        if (m_pWebBrowser2)
        {
            CDuiVariant url;
            url.vt=VT_BSTR;
            url.bstrVal=T2BSTR(lpszUrl);
            HRESULT hr = m_pWebBrowser2->Navigate2(&url, NULL, NULL, NULL, NULL);
        }
    }

    void CWebBrowserUI::Refresh()
    {
        if (m_pWebBrowser2)
        {
            m_pWebBrowser2->Refresh();
        }
    }
    void CWebBrowserUI::GoBack()
    {
        if (m_pWebBrowser2)
        {
            m_pWebBrowser2->GoBack();
        }
    }
    void CWebBrowserUI::GoForward()
    {
        if (m_pWebBrowser2)
        {
            m_pWebBrowser2->GoForward();
        }
    }
    /// DWebBrowserEvents2
    void CWebBrowserUI::BeforeNavigate2( IDispatch *pDisp,VARIANT *&url,VARIANT *&Flags,VARIANT *&TargetFrameName,VARIANT *&PostData,VARIANT *&Headers,VARIANT_BOOL *&Cancel )
    {
        if (m_pWebBrowserEventHandler)
        {
            m_pWebBrowserEventHandler->BeforeNavigate2(this, pDisp,url,Flags,TargetFrameName,PostData,Headers,Cancel);
        }
    }

    void CWebBrowserUI::NavigateError( IDispatch *pDisp,VARIANT * &url,VARIANT *&TargetFrameName,VARIANT *&StatusCode,VARIANT_BOOL *&Cancel )
    {
        if (m_pWebBrowserEventHandler)
        {
            m_pWebBrowserEventHandler->NavigateError(this, pDisp,url,TargetFrameName,StatusCode,Cancel);
        }
    }

    void CWebBrowserUI::NavigateComplete2( IDispatch *pDisp,VARIANT *&url )
    {
        CComPtr<IDispatch> spDoc;   
        m_pWebBrowser2->get_Document(&spDoc);   

        if (spDoc)
        {   
            CComQIPtr<ICustomDoc, &IID_ICustomDoc> spCustomDoc(spDoc);   
            if (spCustomDoc)   
                spCustomDoc->SetUIHandler(this);   
        }

        if (m_pWebBrowserEventHandler)
        {
            m_pWebBrowserEventHandler->NavigateComplete2(this, pDisp,url);
        }
    }

    void CWebBrowserUI::ProgressChange( LONG nProgress, LONG nProgressMax )
    {
        if (m_pWebBrowserEventHandler)
        {
            m_pWebBrowserEventHandler->ProgressChange(this, nProgress,nProgressMax);
        }
    }

    void CWebBrowserUI::NewWindow3( IDispatch **pDisp, VARIANT_BOOL *&Cancel, DWORD dwFlags, BSTR bstrUrlContext, BSTR bstrUrl )
    {
        if (m_pWebBrowserEventHandler)
        {
            m_pWebBrowserEventHandler->NewWindow3(this, pDisp,Cancel,dwFlags,bstrUrlContext,bstrUrl);
        }
    }
    void CWebBrowserUI::CommandStateChange(long Command,VARIANT_BOOL Enable)
    {
        if (m_pWebBrowserEventHandler)
        {
            m_pWebBrowserEventHandler->CommandStateChange(this, Command,Enable);
        }
    }

    void CWebBrowserUI::TitleChange(BSTR bstrTitle)
    {
        if (m_pWebBrowserEventHandler)
        {
            m_pWebBrowserEventHandler->TitleChange(this, bstrTitle);
        }
    }

    void CWebBrowserUI::DocumentComplete(IDispatch *pDisp, VARIANT *&url)
    {
        if (m_pWebBrowserEventHandler)
        {
            m_pWebBrowserEventHandler->DocumentComplete(this, pDisp, url);
        }
    }

    // IDownloadManager
    STDMETHODIMP CWebBrowserUI::Download( /* [in] */ IMoniker *pmk, /* [in] */ IBindCtx *pbc, /* [in] */ DWORD dwBindVerb, /* [in] */ LONG grfBINDF, /* [in] */ BINDINFO *pBindInfo, /* [in] */ LPCOLESTR pszHeaders, /* [in] */ LPCOLESTR pszRedir, /* [in] */ UINT uiCP )
    {
        if (m_pWebBrowserEventHandler)
        {
            return m_pWebBrowserEventHandler->Download(this, pmk,pbc,dwBindVerb,grfBINDF,pBindInfo,pszHeaders,pszRedir,uiCP);
        }
        return S_OK;
    }

    // IDocHostUIHandler
    STDMETHODIMP CWebBrowserUI::ShowContextMenu( DWORD dwID, POINT* pptPosition, IUnknown* pCommandTarget, IDispatch* pDispatchObjectHit )
    {
        if (m_pWebBrowserEventHandler)
        {
            return m_pWebBrowserEventHandler->ShowContextMenu(this, dwID,pptPosition,pCommandTarget,pDispatchObjectHit);
        }
        return S_FALSE;
    }

    STDMETHODIMP CWebBrowserUI::GetHostInfo( DOCHOSTUIINFO* pInfo )
    {
        if (pInfo != NULL) {
            pInfo->dwFlags |= DOCHOSTUIFLAG_NO3DBORDER | DOCHOSTUIFLAG_NO3DOUTERBORDER;
        }
        if (m_pWebBrowserEventHandler) {
            return m_pWebBrowserEventHandler->GetHostInfo(this, pInfo);
        }
        return S_OK;
    }

    STDMETHODIMP CWebBrowserUI::ShowUI( DWORD dwID, IOleInPlaceActiveObject* pActiveObject, IOleCommandTarget* pCommandTarget, IOleInPlaceFrame* pFrame, IOleInPlaceUIWindow* pDoc )
    {
        if (m_pWebBrowserEventHandler)
        {
            return m_pWebBrowserEventHandler->ShowUI(this, dwID,pActiveObject,pCommandTarget,pFrame,pDoc);
        }
        return S_OK;
    }

    STDMETHODIMP CWebBrowserUI::HideUI()
    {
        if (m_pWebBrowserEventHandler)
        {
            return m_pWebBrowserEventHandler->HideUI(this);
        }
        return S_OK;
    }

    STDMETHODIMP CWebBrowserUI::UpdateUI()
    {
        if (m_pWebBrowserEventHandler)
        {
            return m_pWebBrowserEventHandler->UpdateUI(this);
        }
        return S_OK;
    }

    STDMETHODIMP CWebBrowserUI::EnableModeless( BOOL fEnable )
    {
        if (m_pWebBrowserEventHandler)
        {
            return m_pWebBrowserEventHandler->EnableModeless(this, fEnable);
        }
        return E_NOTIMPL;
    }

    STDMETHODIMP CWebBrowserUI::OnDocWindowActivate( BOOL fActivate )
    {
        if (m_pWebBrowserEventHandler)
        {
            return m_pWebBrowserEventHandler->OnDocWindowActivate(this, fActivate);
        }
        return E_NOTIMPL;
    }

    STDMETHODIMP CWebBrowserUI::OnFrameWindowActivate( BOOL fActivate )
    {
        if (m_pWebBrowserEventHandler)
        {
            return m_pWebBrowserEventHandler->OnFrameWindowActivate(this, fActivate);
        }
        return E_NOTIMPL;
    }

    STDMETHODIMP CWebBrowserUI::ResizeBorder( LPCRECT prcBorder, IOleInPlaceUIWindow* pUIWindow, BOOL fFrameWindow )
    {
        if (m_pWebBrowserEventHandler)
        {
            return m_pWebBrowserEventHandler->ResizeBorder(this, prcBorder,pUIWindow,fFrameWindow);
        }
        return E_NOTIMPL;
    }

    STDMETHODIMP CWebBrowserUI::TranslateAccelerator( LPMSG lpMsg, const GUID* pguidCmdGroup, DWORD nCmdID )
    {
        if (m_pWebBrowserEventHandler)
        {
            return m_pWebBrowserEventHandler->TranslateAccelerator(this, lpMsg,pguidCmdGroup,nCmdID);
        }
        return S_FALSE;
    }

    LRESULT CWebBrowserUI::TranslateAccelerator( MSG *pMsg )
    {
        if(pMsg->message < WM_KEYFIRST || pMsg->message > WM_KEYLAST)
            return S_FALSE;

        if( m_pWebBrowser2 == NULL )
            return E_NOTIMPL;

        // 当前Web窗口不是焦点,不处理加速键
        BOOL bIsChild = FALSE;
        HWND hTempWnd = NULL;
        HWND hWndFocus = ::GetFocus();

        hTempWnd = hWndFocus;
        while(hTempWnd != NULL)
        {
            if(hTempWnd == m_hwndHost)
            {
                bIsChild = TRUE;
                break;
            }
            hTempWnd = ::GetParent(hTempWnd);
        }
        if(!bIsChild)
            return S_FALSE;

        IOleInPlaceActiveObject *pObj;
        if (FAILED(m_pWebBrowser2->QueryInterface(IID_IOleInPlaceActiveObject, (LPVOID *)&pObj)))
            return S_FALSE;

        HRESULT hResult = pObj->TranslateAccelerator(pMsg);
        pObj->Release();
        return hResult;
    }

    STDMETHODIMP CWebBrowserUI::GetOptionKeyPath( LPOLESTR* pchKey, DWORD dwReserved )
    {
        if (m_pWebBrowserEventHandler)
        {
            return m_pWebBrowserEventHandler->GetOptionKeyPath(this, pchKey,dwReserved);
        }
        return E_NOTIMPL;
    }

    STDMETHODIMP CWebBrowserUI::GetDropTarget( IDropTarget* pDropTarget, IDropTarget** ppDropTarget )
    {
        if (m_pWebBrowserEventHandler)
        {
            return m_pWebBrowserEventHandler->GetDropTarget(this, pDropTarget,ppDropTarget);
        }
        return S_FALSE;    // 使用系统拖拽
    }

    STDMETHODIMP CWebBrowserUI::GetExternal( IDispatch** ppDispatch )
    {
        if (m_pWebBrowserEventHandler)
        {
            return m_pWebBrowserEventHandler->GetExternal(this, ppDispatch);
        }
        return S_FALSE;
    }

    STDMETHODIMP CWebBrowserUI::TranslateUrl( DWORD dwTranslate, OLECHAR* pchURLIn, OLECHAR** ppchURLOut )
    {
        if (m_pWebBrowserEventHandler)
        {
            return m_pWebBrowserEventHandler->TranslateUrl(this, dwTranslate,pchURLIn,ppchURLOut);
        }
        else
        {
            *ppchURLOut = 0;
            return E_NOTIMPL;
        }
    }

    STDMETHODIMP CWebBrowserUI::FilterDataObject( IDataObject* pDO, IDataObject** ppDORet )
    {
        if (m_pWebBrowserEventHandler)
        {
            return m_pWebBrowserEventHandler->FilterDataObject(this, pDO,ppDORet);
        }
        else
        {
            *ppDORet = 0;
            return E_NOTIMPL;
        }
    }

    void CWebBrowserUI::SetWebBrowserEventHandler( CWebBrowserEventHandler* pEventHandler )
    {
        if ( pEventHandler!=NULL && m_pWebBrowserEventHandler!=pEventHandler)
            m_pWebBrowserEventHandler=pEventHandler;
    }

    void CWebBrowserUI::Refresh2( int Level )
    {
        CDuiVariant vLevel;
        vLevel.vt=VT_I4;
        vLevel.intVal=Level;
        m_pWebBrowser2->Refresh2(&vLevel);
    }

    void CWebBrowserUI::SetAttribute( LPCTSTR pstrName, LPCTSTR pstrValue )
    {
        if (_tcsicmp(pstrName, _T("homepage")) == 0)
        {
            m_sHomePage = pstrValue;
        }
        else if (_tcsicmp(pstrName, _T("autonavi"))==0)
        {
            m_bAutoNavi = (_tcsicmp(pstrValue, _T("true")) == 0);
        }
        else
            CActiveXUI::SetAttribute(pstrName, pstrValue);
    }

    void CWebBrowserUI::NavigateHomePage()
    {
        if (!m_sHomePage.IsEmpty())
            this->NavigateUrl(m_sHomePage);
    }

    void CWebBrowserUI::NavigateUrl( LPCTSTR lpszUrl )
    {
        if (m_pWebBrowser2 && lpszUrl)
        {
            m_pWebBrowser2->Navigate((BSTR)SysAllocString(T2BSTR(lpszUrl)),NULL,NULL,NULL,NULL);
        }
    }

    LPCTSTR CWebBrowserUI::GetClass() const
    {
        return _T("WebBrowserUI");
    }

    LPVOID CWebBrowserUI::GetInterface( LPCTSTR pstrName )
    {
        if( _tcsicmp(pstrName, DUI_CTR_WEBBROWSER) == 0 ) return static_cast<CWebBrowserUI*>(this);
        return CActiveXUI::GetInterface(pstrName);
    }

    void CWebBrowserUI::SetHomePage( LPCTSTR lpszUrl )
    {
        m_sHomePage.Format(_T("%s"),lpszUrl);
    }

    LPCTSTR CWebBrowserUI::GetHomePage()
    {
        return m_sHomePage;
    }

    void CWebBrowserUI::SetAutoNavigation( bool bAuto /*= TRUE*/ )
    {
        if (m_bAutoNavi==bAuto)    return;

        m_bAutoNavi=bAuto;
    }

    bool CWebBrowserUI::IsAutoNavigation()
    {
        return m_bAutoNavi;
    }

    STDMETHODIMP CWebBrowserUI::QueryService( REFGUID guidService, REFIID riid, void** ppvObject )
    {
        HRESULT hr = E_NOINTERFACE;
        *ppvObject = NULL;

        if ( guidService == SID_SDownloadManager && riid == IID_IDownloadManager)
        {
            *ppvObject = this;
            return S_OK;
        }
        if(guidService == SID_SInternetSecurityManager && riid == IID_IInternetSecurityManager) {
            *ppvObject = this;
            return S_OK;
        }
        return hr;
    }

    HRESULT CWebBrowserUI::RegisterEventHandler( BOOL inAdvise )
    {
        CComPtr<IWebBrowser2> pWebBrowser;
        CComPtr<IConnectionPointContainer>  pCPC;
        CComPtr<IConnectionPoint> pCP;
        HRESULT hr = GetControl(IID_IWebBrowser2, (void**)&pWebBrowser);
        if (FAILED(hr))
            return hr;
        hr=pWebBrowser->QueryInterface(IID_IConnectionPointContainer,(void **)&pCPC);
        if (FAILED(hr))
            return hr;
        hr=pCPC->FindConnectionPoint(DIID_DWebBrowserEvents2,&pCP);
        if (FAILED(hr))
            return hr;

        if (inAdvise)
        {
            hr = pCP->Advise((IDispatch*)this, &m_dwCookie);
        }
        else
        {
            hr = pCP->Unadvise(m_dwCookie);
        }
        return hr; 
    }

    DISPID CWebBrowserUI::FindId( IDispatch *pObj, LPOLESTR pName )
    {
        DISPID id = 0;
        if(FAILED(pObj->GetIDsOfNames(IID_NULL,&pName,1,LOCALE_SYSTEM_DEFAULT,&id))) id = -1;
        return id;
    }

    HRESULT CWebBrowserUI::InvokeMethod( IDispatch *pObj, LPOLESTR pMehtod, VARIANT *pVarResult, VARIANT *ps, int cArgs )
    {
        DISPID dispid = FindId(pObj, pMehtod);
        if(dispid == -1) return E_FAIL;

        DISPPARAMS dispparams;
        dispparams.cArgs = cArgs;
        dispparams.rgvarg = ps;
        dispparams.cNamedArgs = 0;
        dispparams.rgdispidNamedArgs = NULL;

        return pObj->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, &dispparams, pVarResult, NULL, NULL);
    }

    HRESULT CWebBrowserUI::GetProperty( IDispatch *pObj, LPOLESTR pName, VARIANT *pValue )
    {
        DISPID dispid = FindId(pObj, pName);
        if(dispid == -1) return E_FAIL;

        DISPPARAMS ps;
        ps.cArgs = 0;
        ps.rgvarg = NULL;
        ps.cNamedArgs = 0;
        ps.rgdispidNamedArgs = NULL;

        return pObj->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET, &ps, pValue, NULL, NULL);
    }

    HRESULT CWebBrowserUI::SetProperty( IDispatch *pObj, LPOLESTR pName, VARIANT *pValue )
    {
        DISPID dispid = FindId(pObj, pName);
        if(dispid == -1) return E_FAIL;

        DISPPARAMS ps;
        ps.cArgs = 1;
        ps.rgvarg = pValue;
        ps.cNamedArgs = 0;
        ps.rgdispidNamedArgs = NULL;

        return pObj->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYPUT, &ps, NULL, NULL, NULL);
    }

    IDispatch* CWebBrowserUI::GetHtmlWindow()
    {
        IDispatch* pDp =  NULL;
        HRESULT hr;
        if (m_pWebBrowser2)
            hr=m_pWebBrowser2->get_Document(&pDp);

        if (FAILED(hr))
            return NULL;

        CComQIPtr<IHTMLDocument2> pHtmlDoc2 = pDp;

        if (pHtmlDoc2 == NULL)
            return NULL;

        hr=pHtmlDoc2->get_parentWindow(&_pHtmlWnd2);

        if (FAILED(hr))
            return NULL;

        IDispatch *pHtmlWindown = NULL;
        hr=_pHtmlWnd2->QueryInterface(IID_IDispatch, (void**)&pHtmlWindown);
        if (FAILED(hr))
            return NULL;

        return pHtmlWindown;
    }

    IWebBrowser2* CWebBrowserUI::GetWebBrowser2( void )
    {
        return m_pWebBrowser2;
    }

    HRESULT STDMETHODCALLTYPE CWebBrowserUI::QueryStatus( __RPC__in_opt const GUID *pguidCmdGroup, ULONG cCmds, __RPC__inout_ecount_full(cCmds ) OLECMD prgCmds[ ], __RPC__inout_opt OLECMDTEXT *pCmdText )
    {
        HRESULT hr = OLECMDERR_E_NOTSUPPORTED;
        return hr;
    }

    HRESULT STDMETHODCALLTYPE CWebBrowserUI::Exec( __RPC__in_opt const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, __RPC__in_opt VARIANT *pvaIn, __RPC__inout_opt VARIANT *pvaOut )
    {
        HRESULT hr = S_OK;

        if (pguidCmdGroup && IsEqualGUID(*pguidCmdGroup, CGID_DocHostCommandHandler))
        {

            switch (nCmdID) 
            {

            case OLECMDID_SHOWSCRIPTERROR:
                {
                    IHTMLDocument2*             pDoc = NULL;
                    IHTMLWindow2*               pWindow = NULL;
                    IHTMLEventObj*              pEventObj = NULL;
                    BSTR                        rgwszNames[5] = 
                    { 
                        SysAllocString(L"errorLine"),
                        SysAllocString(L"errorCharacter"),
                        SysAllocString(L"errorCode"),
                        SysAllocString(L"errorMessage"),
                        SysAllocString(L"errorUrl")
                    };
                    DISPID                      rgDispIDs[5];
                    VARIANT                     rgvaEventInfo[5];
                    DISPPARAMS                  params;
                    BOOL                        fContinueRunningScripts = true;
                    int                         i;

                    params.cArgs = 0;
                    params.cNamedArgs = 0;

                    // Get the document that is currently being viewed.
                    hr = pvaIn->punkVal->QueryInterface(IID_IHTMLDocument2, (void **) &pDoc);    
                    // Get document.parentWindow.
                    hr = pDoc->get_parentWindow(&pWindow);
                    pDoc->Release();
                    // Get the window.event object.
                    hr = pWindow->get_event(&pEventObj);
                    // Get the error info from the window.event object.
                    for (i = 0; i < 5; i++) 
                    {  
                        // Get the property's dispID.
                        hr = pEventObj->GetIDsOfNames(IID_NULL, &rgwszNames[i], 1, 
                            LOCALE_SYSTEM_DEFAULT, &rgDispIDs[i]);
                        // Get the value of the property.
                        hr = pEventObj->Invoke(rgDispIDs[i], IID_NULL,
                            LOCALE_SYSTEM_DEFAULT,
                            DISPATCH_PROPERTYGET, &params, &rgvaEventInfo[i],
                            NULL, NULL);
                        SysFreeString(rgwszNames[i]);
                    }

                    // At this point, you would normally alert the user with 
                    // the information about the error, which is now contained
                    // in rgvaEventInfo[]. Or, you could just exit silently.

                    (*pvaOut).vt = VT_BOOL;
                    if (fContinueRunningScripts)
                    {
                        // Continue running scripts on the page.
                        (*pvaOut).boolVal = VARIANT_TRUE;
                    }
                    else
                    {
                        // Stop running scripts on the page.
                        (*pvaOut).boolVal = VARIANT_FALSE;   
                    } 
                    break;
                }
            default:
                hr = OLECMDERR_E_NOTSUPPORTED;
                break;
            }
        }
        else
        {
            hr = OLECMDERR_E_UNKNOWNGROUP;
        }
        return (hr);
    }
}